package com.earthea.common.jackson;

import com.earthea.common.annotation.Anonymize;
import com.earthea.common.enumeration.AnonymizeType;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;

import java.io.IOException;
import java.util.EnumMap;
import java.util.Map;

public class AnonymizeSerializer extends StdSerializer<Object> implements ContextualSerializer {

    private static final Map<AnonymizeType, AnonymizeSerializer> SERIALIZERS = new EnumMap<>(AnonymizeType.class);

    private final AnonymizeType anonymizeType;

    public AnonymizeSerializer() {
        super(Object.class);
        this.anonymizeType = null;
    }

    public AnonymizeSerializer(AnonymizeType anonymizeType) {
        super(Object.class);
        this.anonymizeType = anonymizeType;
    }

    @Override
    public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (value == null) {
            gen.writeNull();
            return;
        }
        gen.writeString(anonymize(value.toString()));
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        // 在这里获取字段的注解
        Anonymize annot = null;
        if (property != null) {
            annot = property.getAnnotation(Anonymize.class);
            if (annot == null) {
                annot = property.getContextAnnotation(Anonymize.class);
            }
        }

        if (annot != null) {
            Anonymize finalAnnot = annot;
            return SERIALIZERS.computeIfAbsent(annot.type(), k -> new AnonymizeSerializer(finalAnnot.type()));
        }
        return this;
    }

    private String anonymize(String value) {
        if (anonymizeType == null) {
            return value;
        }
        return switch (anonymizeType) {
            case AnonymizeType.PASSWORD -> anonymizePassword();
            case AnonymizeType.PHONE -> anonymizePhone(value);
            case AnonymizeType.EMAIL -> anonymizeEmail(value);
            default -> defaultAnonymize(value);
        };
    }

    private String anonymizePassword() {
        return "*".repeat(6);
    }

    private String anonymizePhone(String phone) {
        if (phone.length() != 11) {
            return defaultAnonymize(phone);
        }
        return phone.substring(0, 3) + "*".repeat(4) + phone.substring(7);
    }

    private String anonymizeEmail(String email) {
        int atIndex = email.indexOf('@');
        if (atIndex <= 1) {
            return defaultAnonymize(email);
        }
        String domain = email.substring(atIndex);
        String name = email.substring(0, atIndex);

        if (name.length() == 2) {
            return name.charAt(0) + "*".repeat(5) + domain;
        }
        return name.substring(0, 2) + "*".repeat(4) + domain;
    }

    private String defaultAnonymize(String value) {
        if (value.length() < 2) {
            return "*".repeat(6);
        } else if (value.length() == 2) {
            return value.charAt(0) + "*".repeat(5);
        } else if (value.length() <= 6) {
            return value.charAt(0) + "*".repeat(4) + value.substring(value.length() - 1);
        } else if (value.length() <= 10) {
            return value.substring(0, 2) + "*".repeat(4) + value.substring(value.length() - 2);
        } else if (value.length() <= 16) {
            return value.substring(0, 3) + "*".repeat(4) + value.substring(value.length() - 3);
        } else {
            return value.substring(0, 4) + "*".repeat(4) + value.substring(value.length() - 4);
        }
    }

}